#include "PlatformProperty.h"

MAPPING_VALUE(SeatBackrestMode, sdb::SwtHozlSts1, sdb::SwtHozlSts1::Idle)
MAPPING_ITEM(SeatBackrestMode::SEAT_BACKREST_OFF, sdb::SwtHozlSts1::Idle)
MAPPING_ITEM(SeatBackrestMode::SEAT_BACKREST_FORWARD, sdb::SwtHozlSts1::Fwd)
MAPPING_ITEM(SeatBackrestMode::SEAT_BACKREST_BACKWARD, sdb::SwtHozlSts1::Backw)
MAPPING_END
MAPPING_VALUE(sdb::SwtHozlSts1, SeatBackrestMode, SeatBackrestMode::SEAT_BACKREST_OFF)
MAPPING_ITEM(sdb::SwtHozlSts1::Idle, SeatBackrestMode::SEAT_BACKREST_OFF)
MAPPING_ITEM(sdb::SwtHozlSts1::Fwd, SeatBackrestMode::SEAT_BACKREST_FORWARD)
MAPPING_ITEM(sdb::SwtHozlSts1::Backw, SeatBackrestMode::SEAT_BACKREST_BACKWARD)
MAPPING_END

std::map<int32_t, int32_t> m_SeatAdjustmentVFCAngle2Move;

static bool isMoveLimited(int32_t pos, SeatBackrestMode seatBackrestMode) {
    int32_t min = lcfg::LocalConfig::getInstance().getInt<int32_t>(lcfg::LCFG_Min_Backrest_angle);
    int32_t max = lcfg::LocalConfig::getInstance().getInt<int32_t>(lcfg::LCFG_Max_Backrest_angle);
    VHALOG.d("SEAT_BACKREST_ANGLE_2_MOVE isMoveLimited pos=%d, min=%d, max=%d seatBackrestMode=%d", pos, min, max, toInt(seatBackrestMode));
    if (seatBackrestMode == SeatBackrestMode::SEAT_BACKREST_FORWARD && pos <= min) {
        VHALOG.e("SEAT_BACKREST_ANGLE_2_MOVE can not move forward, the pos is min");
        return true;
    } else if (seatBackrestMode == SeatBackrestMode::SEAT_BACKREST_BACKWARD && pos >= max) {
        VHALOG.e("SEAT_BACKREST_ANGLE_2_MOVE can not move backward, the pos is max");
        return true;
    }
    return false;
}

void SeatAdjustmentChangeVFC_IdleToOtherAngle2Move(SignalTX iSignal, int32_t iValue) {
    int32_t ikey = static_cast<int32_t>(iSignal);
    std::map<int32_t, int32_t>::iterator it = m_SeatAdjustmentVFCAngle2Move.find(ikey);
    int32_t idle = static_cast<int32_t>(sdb::SwtVertSts1::Idle);
    if (it == m_SeatAdjustmentVFCAngle2Move.end()) {
        m_SeatAdjustmentVFCAngle2Move[ikey] = idle;
    }
    VHALOG.d("SeatAdjustmentChangeVFC_IdleToOtherAngle2Move-iValue=%d,last=%d,Signal=%d,key=%d", iValue,
             m_SeatAdjustmentVFCAngle2Move[ikey], iSignal, ikey);
    if (idle == m_SeatAdjustmentVFCAngle2Move[ikey] && idle != iValue &&
        !SIGNAL.usgModeIs(sdb::UsgModSts1::UsgModAbdnd)) {
        SIGNAL.setCB_VFC_SeatComfortFunctions(sdb::OnOff1::On);
    }
    m_SeatAdjustmentVFCAngle2Move[ikey] = iValue;
}

//  N5  [SW_FC_004_050] 3.2.19 第二排靠背调节 2ndRowSeatBackrestAdjustment--前后角度
SYSTEM_READ_WRITE_PROPERTY(SEAT_BACKREST_ANGLE_2_MOVE, SeatBackrestMode) {
    builder.area(VehicleAreaSeat::ROW_2_LEFT)
        .initValue([]() { return SeatBackrestMode::SEAT_BACKREST_OFF; })
        .withStatusBySignals(
            []([[maybe_unused]] const PropertyStatus& last) {
                sdb::Boolean rowSecLeBtnPsd = SIGNAL.getRowSecLeBtnPsd();
                VHALOG.d(
                    "SEAT_BACKREST_ANGLE_2_MOVE drvr status Change carmod[%d], usgmod[%d], "
                    "cc474[%d], rowSecLeBtnPsd[%d]",
                    SIGNAL.getVehModMngtGlbSafe1CarModSts1(), SIGNAL.getVehModMngtGlbSafe1UsgModSts(),
                    SIGNAL.getcarconfig474(), static_cast<int32_t>(rowSecLeBtnPsd));

                if (SIGNAL.carConfigIs(SignalRX::carconfig474,
                                       sdb::CarConfig474::_03,
                                       sdb::CarConfig474::_04,
                                       sdb::CarConfig474::_05,
                                       sdb::CarConfig474::_81)) {
                    if (SIGNAL.carModeIs(sdb::CarModSts1::CarModCrash,
                                         sdb::CarModSts1::CarModDyno,
                                         sdb::CarModSts1::CarModNorm) &&
                        SIGNAL.usgModeIs(sdb::UsgModSts1::UsgModInActv,
                                         sdb::UsgModSts1::UsgModCnvinc,
                                         sdb::UsgModSts1::UsgModActv,
                                         sdb::UsgModSts1::UsgModDrvg) &&
                        rowSecLeBtnPsd == sdb::Boolean::FALSE) {
                        VHALOG.d("SEAT_BACKREST_ANGLE_2_MOVE drvr  Active");
                        return PropertyStatus::Active;
                    }
                    VHALOG.d("SEAT_BACKREST_ANGLE_2_MOVE drvr  NotActive");
                    return PropertyStatus::NotActive;
                }
                VHALOG.d("SEAT_BACKREST_ANGLE_2_MOVE drvr  NotAvailable");
                return PropertyStatus::NotAvailable;
            },
            SignalRX::carconfig474,
            SignalRX::RowSecLeBtnPsd,
            SignalRX::VehModMngtGlbSafe1UsgModSts,
            SignalRX::VehModMngtGlbSafe1CarModSts1)
        .withValueBySignals(
            []([[maybe_unused]] const SeatBackrestMode& last) {
                sdb::SwtHozlSts1 SwtSldSts = SIGNAL.getSeatRowSecLeSwtStsPassSeatSwtInclSts();
                auto angle = SIGNAL.getRowSecLeInclPosAngle();
                sdb::Boolean rowSecLeBtnPsd = SIGNAL.getRowSecLeBtnPsd();
                VHALOG.d("GET SEAT_BACKREST_ANGLE_2_MOVE drvr SeatRowSecLeSwtStsPassSeatSwtInclSts[%d] ,angle[%d],rowSecLeBtnPsd[%d]",
                         SwtSldSts, angle, static_cast<int32_t>(rowSecLeBtnPsd));

                if (rowSecLeBtnPsd == sdb::Boolean::TRUE ||
                    isMoveLimited(angle, mappingValue(SwtSldSts, SeatBackrestMode::SEAT_BACKREST_OFF))) {
                    VHALOG.d("Call SEAT_BACKREST_ANGLE_2_MOVE drvr trigger to idle");
                    SeatAdjustmentChangeVFC_IdleToOtherAngle2Move(SignalTX::BackrestAdjmtRowSecLe,
                                                                  static_cast<int32_t>(sdb::SwtHozlSts1::Idle));
                    SIGNAL.setBackrestAdjmtRowSecLe(sdb::SwtHozlSts1::Idle);
                    return SeatBackrestMode::SEAT_BACKREST_OFF;
                }
                return mappingValue(SwtSldSts, SeatBackrestMode::SEAT_BACKREST_OFF);
            },
            SignalRX::SeatRowSecLeSwtStsPassSeatSwtInclSts,
            SignalRX::RowSecLeBtnPsd,
            SignalRX::RowSecLeInclPosAngle)
        .onSetProperty([](const SeatBackrestMode value) {
            if (value != SeatBackrestMode::SEAT_BACKREST_FORWARD &&
                value != SeatBackrestMode::SEAT_BACKREST_BACKWARD &&
                value != SeatBackrestMode::SEAT_BACKREST_OFF) {
                VHALOG.e("SEAT_BACKREST_ANGLE_2_MOVE drvr: param invaild");
                return;
            }
            auto angle = SIGNAL.getRowSecRiInclPosAngle();
            if (isMoveLimited(angle, value)) {
                VHALOG.e("SEAT_BACKREST_ANGLE_2_MOVE: drvr param invaild(MoveLimited),the angle is %d", angle);
                return;
            }
            VHALOG.d("SEAT_BACKREST_ANGLE_2_MOVE drvr value is %d", value);

            sdb::SwtHozlSts1 tempBackrestAdjmtRowSecLe = mappingValue(value, sdb::SwtHozlSts1::Idle);
            SeatAdjustmentChangeVFC_IdleToOtherAngle2Move(SignalTX::BackrestAdjmtRowSecLe,
                                                          static_cast<int32_t>(tempBackrestAdjmtRowSecLe));
            SIGNAL.setBackrestAdjmtRowSecLe(tempBackrestAdjmtRowSecLe);
        })
        .area(VehicleAreaSeat::ROW_2_RIGHT)
        .initValue([]() { return SeatBackrestMode::SEAT_BACKREST_OFF; })
        .withStatusBySignals(
            []([[maybe_unused]] const PropertyStatus& last) {
                sdb::Boolean rowSecRiBtnPsd = SIGNAL.getRowSecRiBtnPsd();
                VHALOG.d(
                    "SEAT_BACKREST_ANGLE_2_MOVE pass status Change carmod[%d], usgmod[%d], "
                    "cc474[%d] ",
                    SIGNAL.getVehModMngtGlbSafe1CarModSts1(),
                    SIGNAL.getVehModMngtGlbSafe1UsgModSts(), SIGNAL.getcarconfig474(),
                    SIGNAL.getcarconfig551(), static_cast<int32_t>(rowSecRiBtnPsd));
                if (SIGNAL.carConfigIs(SignalRX::carconfig474,
                                       sdb::CarConfig474::_03,
                                       sdb::CarConfig474::_04,
                                       sdb::CarConfig474::_05,
                                       sdb::CarConfig474::_81)) {
                    if (SIGNAL.carModeIs(sdb::CarModSts1::CarModCrash,
                                         sdb::CarModSts1::CarModDyno,
                                         sdb::CarModSts1::CarModNorm) &&
                        SIGNAL.usgModeIs(sdb::UsgModSts1::UsgModInActv,
                                         sdb::UsgModSts1::UsgModCnvinc,
                                         sdb::UsgModSts1::UsgModActv,
                                         sdb::UsgModSts1::UsgModDrvg) &&
                        rowSecRiBtnPsd == sdb::Boolean::FALSE) {
                        VHALOG.d("SEAT_BACKREST_ANGLE_2_MOVE pass  Active");
                        return PropertyStatus::Active;
                    }
                    VHALOG.d("SEAT_BACKREST_ANGLE_2_MOVE pass  NotActive");
                    return PropertyStatus::NotActive;
                }
                VHALOG.d("SEAT_BACKREST_ANGLE_2_MOVE pass  NotAvailable");
                return PropertyStatus::NotAvailable;
            },
            SignalRX::carconfig474,
            SignalRX::RowSecRiBtnPsd,
            SignalRX::VehModMngtGlbSafe1UsgModSts,
            SignalRX::VehModMngtGlbSafe1CarModSts1)
        .withValueBySignals(
            []([[maybe_unused]] const SeatBackrestMode& last) {
                sdb::SwtHozlSts1 SwtSldSts = SIGNAL.getSeatRowSecRiSwtStsPassSeatSwtInclSts();
                auto angle = SIGNAL.getRowSecRiInclPosAngle();
                sdb::Boolean rowSecRiBtnPsd = SIGNAL.getRowSecRiBtnPsd();
                VHALOG.d("withValueBySignals SEAT_BACKREST_ANGLE_2_MOVE pass SeatRowSecRiSwtStsPassSeatSwtInclSts[%d],angle[%d] rowSecRiBtnPsd[%d]",
                         SwtSldSts, angle, static_cast<int32_t>(rowSecRiBtnPsd));

                if (rowSecRiBtnPsd == sdb::Boolean::TRUE ||
                    isMoveLimited(angle, mappingValue(SwtSldSts, SeatBackrestMode::SEAT_BACKREST_OFF))) {
                    VHALOG.d("Call SEAT_BACKREST_ANGLE_2_MOVE pass trigger to idle");
                    SeatAdjustmentChangeVFC_IdleToOtherAngle2Move(SignalTX::BackrestAdjmtRowSecRi,
                                                                  static_cast<int32_t>(sdb::SwtHozlSts1::Idle));
                    SIGNAL.setBackrestAdjmtRowSecRi(sdb::SwtHozlSts1::Idle);
                    return SeatBackrestMode::SEAT_BACKREST_OFF;
                }
                return mappingValue(SwtSldSts, SeatBackrestMode::SEAT_BACKREST_OFF);
            },
            SignalRX::SeatRowSecRiSwtStsPassSeatSwtInclSts,
            SignalRX::RowSecRiBtnPsd,
            SignalRX::RowSecRiInclPosAngle)
        .onSetProperty([](const SeatBackrestMode value) {
            if (value != SeatBackrestMode::SEAT_BACKREST_FORWARD &&
                value != SeatBackrestMode::SEAT_BACKREST_BACKWARD &&
                value != SeatBackrestMode::SEAT_BACKREST_OFF) {
                VHALOG.e("SEAT_BACKREST_ANGLE_2_MOVE pass: param invaild");
                return;
            }

            auto angle = SIGNAL.getRowSecRiInclPosAngle();
            if (isMoveLimited(angle, value)) {
                VHALOG.e("SEAT_BACKREST_ANGLE_2_MOVE:  pass param invaild(MoveLimited),the angle is %d", angle);
                return;
            }
            VHALOG.d("SEAT_BACKREST_ANGLE_2_MOVE pass value is %d", value);
            sdb::SwtHozlSts1 tempBackrestAdjmtRowSecRi = mappingValue(value, sdb::SwtHozlSts1::Idle);
            SeatAdjustmentChangeVFC_IdleToOtherAngle2Move(SignalTX::BackrestAdjmtRowSecRi,
                                                          static_cast<int32_t>(tempBackrestAdjmtRowSecRi));
            SIGNAL.setBackrestAdjmtRowSecRi(tempBackrestAdjmtRowSecRi);
        });
}